# -*- coding: utf-8 -*-
class Person(object):
    count = 0
    __count = 0
    weights=[]
    address = 'Earth' #类属性
    def __init__(self,name,gender,birth,weight,**kw):
        Person.count = Person.count + 1
        Person.__count = Person.__count + 1
        self.name=name
        self.gender = gender
        self.birth = birth
        self._weight = weight
        Person.weights.append(weight)
        for k, v in kw.iteritems():
            setattr(self, k, v)
        print "Person类",Person.__count
        
    #''' 得到自己的体重排名'''
    def get_orders(self):
        return getOrdersIndex(Person.weights,self._weight)
    #类方法
    @classmethod
    def how_many(cls):
        return cls.__count
    
    def whoAmI(self):
        return 'I am a Person, my name is %s' % self.name
    
#自定义获取排名的方法
def getOrdersIndex(list1,weight):
        #倒序排序
        l2 = sorted(list1,lambda y,x :cmp(x, y))
        #print "分数集合l2",l2
        num=0
        for l1 in l2:
            num = num + 1
            if l1 == weight:
                break
        return num
            
        
xiaoming = Person('Xiao Ming', 'Male', '1991-1-1',77,job='student')
xiaohong = Person('Xiao Hong', 'Female','1992-2-2',89)
xiaohong1 = Person('Xiao Hong', 'Female','1992-2-2',79)
xiaohong2 = Person('Xiao Hong', 'Female','1992-2-2',99)
print xiaoming._weight
#当实例属性和类属性重名时，实例属性优先级高，它将屏蔽掉对类属性的访问。
print xiaoming.address
xiaoming.address = 'hangzhou'
print xiaoming.address
Person.address = 'china' #类属性进行改变
print xiaohong.address
print '总共',Person.count,'个Person实例,xiaoming的体重排名是第',xiaoming.get_orders(),"名"
print Person.how_many()

class StudentStudent(Person):
    def __init__(self, name, gender,birth,weight,score):
        super(Student, self).__init__(name, gender,birth,weight)
        self.score = score
    def whoAmI(self):
        return 'I am a Student,my name is %s'%self.name
    def read(self):
        return r'["Tim", "Bob", "Alice"]'
student1 = Student('Xiao hua', 'Male', '1991-1-1',77,89)
print student1.name,'体重排名',student1.get_orders(),'体重',student1._weight,'成绩',student1.score

class Teacher(Person):
    def __init__(self, name, gender,birth,weight,jiaoling):
        super(Teacher, self).__init__(name, gender,birth,weight)
        self.jiaoling = jiaoling
    def whoAmI(self):
        return 'I am a teacher,my name is %s,I have %s years of teaching experience in Chinese'%(self.name,self.jiaoling)
t1 = Teacher('Xiaolaoshi', 'Male', '1991-1-1',70,4)
print t1.name

#isinstance 应用
print 'isinstance应用', isinstance(t1, Person) ,isinstance(t1, Student) 

print'python多态的概念：在一个函数中，如果我们接收一个变量 x，则无论该 x 是 Person、Student还是 Teacher，都可以正确打印出结果：这种行为称为多态。例如：函数who_am_i(x)'
print '多态性练习',student1.whoAmI(),'this is my teacher introduction,"',t1.whoAmI(),'."'
print '多态性与java的区别:动态语言调用实例方法，不检查类型，只要方法存在，参数正确，就可以调用'
class Book(object):
    def whoAmI(self):
        return 'I am a book'
b = Book();
def who_am_i(x):
    print x.whoAmI()

who_am_i(t1)
who_am_i(b)

import json
print json.load(student1)

print '多重继承'
class A(object):
    def __init__(self, a):
        print 'init A...'
        self.a = a

class B(A):
    def __init__(self, a):
        super(B, self).__init__(a)
        print 'init B...'

class C(A):
    def __init__(self, a):
        super(C, self).__init__(a)
        print 'init C...'

class D(B, C):
    def __init__(self, a):
        super(D, self).__init__(a)
        print 'init D...'
'像这样，D 同时继承自 B 和 C，也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时，A 虽然被继承了两次，但__init__()只调用一次：'
d = D('d')
'多重继承的目的是从两种继承树中分别选择并继承出子类，以便组合功能使用。'


class SkillMixin(object):
    def __init__(self,a):
        print '运动'

class BasketballMixin(SkillMixin):
    def __init__(self):
        super(BasketballMixin, self).__init__()
    def skill(self):
        return 'can play basketball'

class FootballMixin(SkillMixin):
    def __init__(self):
        super(FootballMixin, self).__init__()
    def skill(self):
        return 'can play football'
    
print '会玩篮球的学生'
class CanBasketballStudent(Student,BasketballMixin):
    def __init__(self,name, gender,birth,weight,score):
        super(CanBasketballStudent, self).__init__(name, gender,birth,weight,score)
s1 = CanBasketballStudent('Xiao hua', 'Male', '1991-1-1',77,89)
print s1.name,s1.skill()

print 'python中获取对象信息'
print type(s1)#用 type() 函数获取变量的类型，它返回一个 Type 对象
print type(1)
print dir(s1) # dir() 函数获取变量的所有属性
print getattr(s1, 'name')  # 获取name属性
setattr(s1, 'name','Adam')  # 设置新的name属性
print getattr(s1, 'name')  # 获取name属性
print filter(lambda x : x.find("__") <= 0 and x.endswith("__") == False,dir(s1))#x.find("__")找到目标字符串的下表，没有则返回-1

print filter(lambda x : x%2 == 1 and x%3 ==0 and x%4 == 1 and x % 5 ==4 and x%6 ==3 and x%7 ==0 and x%8 ==1 and x%9 ==0 ,range(1,100000))#x.find("__")找到目标字符串的下表，没有则返回-1


'''
在Python中，类通过 class 关键字定义。按照 Python 的编程习惯，类名以大写字母开头，紧接着是(object)，表示该类是从哪个类继承下来的。类的实例的创建，在定义 Person 类时，可以为Person类添加一个特殊的__init__()方法，当创建实例时，__init__()方法被自动调用，我们就能在此为每个实例都统一加上以下属性：__init__() 方法的第一个参数必须是self（也可以用别的名字，但建议使用习惯用法），后续参数则可以自由指定，和定义函数没有任何区别。
Python对属性权限的控制是通过属性名来实现的：
以双下划线开头的"__job"不能直接被外部访问。
但是，如果一个属性以"__xxx__"的形式定义，那它又可以被外部访问了，以"__xxx__"定义的属性在Python的类中被称为特殊属性，有很多预定义的特殊属性可以使用，通常我们不要把普通属性用"__xxx__"定义。
以单下划线开头的属性"_xxx"虽然也可以被外部访问，但是，按照习惯，他们不应该被外部访问。
类是模板，而实例则是根据类创建的对象。
绑定在一个实例上的属性不会影响其他实例，但是，类本身也是一个对象，如果在类上绑定一个属性，则所有实例都可以访问类的属性，并且，所有实例访问的类属性都是同一个！也就是说，实例属性每个实例各自拥有，互相独立，而类属性有且只有一份。
当实例属性和类属性重名时，实例属性优先级高，它将屏蔽掉对类属性的访问。
在 class 中定义的实例方法其实也是属性，它实际上是一个函数对象：例如xiaoming.get_orders得到的是函数对象，但这个函数是一个绑定到实例的函数。xiaoming.get_orders()才是方法调用。
因为方法也是一个属性，所以，它也可以动态地添加到实例上，只是需要用 types.MethodType() 把一个函数变为一个方法
p1.get_grade = types.MethodType(fn_get_grade, p1, Person) p1是实例，get_grade是方法名，fn_get_grade是类外的一个方法，Person是类
和属性类似，方法也分实例方法和类方法
实例方法第一个参数 self 是实例本身。要在class中定义类方法，需要通过标记一个 @classmethod，该方法将绑定到类上，而非类的实例。
类方法的第一个参数将传入类本身，通常将参数名命名为cls，上面的 cls.count 实际上相当于 Person.count

继承
一定要用 super(Student, self).__init__(name, gender) 去初始化父类，否则，继承自 Person 的 Student 将没有 name 和 gender。
函数isinstance()可以判断一个变量的类型，既可以用在Python内置的数据类型如str、list、dict，也可以用在我们自定义的类，它们本质上都是数据类型。

多态
python多态的概念：在一个函数中，如果我们接收一个变量 x，则无论该 x 是 Person、Student还是 Teacher，都可以正确打印出结果：这种行为称为多态。
多态性与java的区别:
也就是说，方法调用将作用在 x 的实际类型上。s 是Student类型，它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法，但调用 s.whoAmI()总是先查找它自身的定义，如果没有定义，
则顺着继承链向上查找，直到在某个父类中找到为止。由于Python是动态语言，所以，传递给函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以，只要它有一个whoAmI()的方法即可：
这是动态语言和静态语言（例如Java）最大的差别之一。动态语言调用实例方法，不检查类型，只要方法存在，参数正确，就可以调用。
Python提供了open()函数来打开一个磁盘文件，并返回 File 对象。File对象有一个read()方法可以读取文件内容：
例如，从文件读取内容并解析为JSON结果：
import json
f = open('/path/to/file.json', 'r')
print json.load(f)
由于Python的动态特性，json.load()并不一定要从一个File对象读取内容。任何对象，只要有read()方法，就称为File-like Object，都可以传给json.load()。
python中获取对象信息
print type(s1)#用 type() 函数获取变量的类型，它返回一个 Type 对象
print type(1)
print dir(s1) # dir() 函数获取变量的所有属性
print getattr(s1, 'name')  # 获取name属性
setattr(s1, 'name','Adam')  # 设置新的name属性
print getattr(s1, 'name')  # 获取name属性
print filter(lambda x : x.find("__") <= 0 and x.endswith("__") == False,dir(s1))#x.find("__")找到目标字符串的下表，没有则返回-1
'''
print type(Student)
print type(s1)
print sum(filter(lambda x: x%2 != 0,range(1,101)))

print sum(range(1,101,2))